﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeGenerator.CSharp
{
    /// <summary>
    /// Defines a modifier that prepends the declaration of a code unit (e.g., public, private, partial, etc.)
    /// </summary>
    public class Modifier
    {
		public Modifier(string name) { this.Name = name; }
		public string Name { get; set; }

		/// <summary>
		/// Identifies a string representation of this modifier.
		/// </summary>
		/// <returns>A string suitable for code generation.</returns>
		public override string ToString()
		{
			return this.Name;
		}

    }

    /// <summary>
    /// Defines a collection of modifiers.
    /// </summary>
    public class ModifierCollection : List<Modifier>
    {
        public ModifierCollection() { }
        public ModifierCollection(params Modifier[] modifiers)
        {
            foreach (Modifier ThisModifier in modifiers)
                this.Add(ThisModifier);
        }
        public ModifierCollection(params ModifierCollection[] modifiers)
        {
            foreach (ModifierCollection ThisModifierCollection in modifiers)
                this.AddRange(ThisModifierCollection);
        }

        public static ModifierCollection operator +(ModifierCollection a, ModifierCollection b)
        {
            ModifierCollection modifiers = new ModifierCollection();
            modifiers.AddRange(a);
            modifiers.AddRange(b);
            return modifiers;
        }

        /// <summary>
        /// Identifies a string representation of all the modifiers in this collection.
        /// </summary>
        /// <returns>A string suitable for code generation.</returns>
        public override string ToString()
        {
            string ReturnValue = string.Empty;
            foreach (Modifier ThisModifier in this)
            {
                ReturnValue += ThisModifier.ToString() + " ";
            }
            return ReturnValue.Trim();
        }

		/// <summary>
		/// Identifies if this collection contains the Abstract modifier.
		/// </summary>
		internal bool IsAbstract
		{
			get { return this.Contains(Modifiers.Abstract[0]); }
		}

		internal bool IsNotAbstract
		{
			get { return !this.IsAbstract; }
		}

        /// <summary>
        /// Identifies if this collection contains the Partial modifier.
        /// </summary>
        internal bool IsPartial
        {
            get { return this.Contains(Modifiers.Partial[0]); }
        }

        internal bool IsNotPartial
        {
            get { return !this.IsPartial; }
        }

    }

    /// <summary>
    /// A set of predefined modifiers.
    /// </summary>
    public class Modifiers
    {
        public static ModifierCollection Private = new ModifierCollection(new Modifier("private"));
        public static ModifierCollection Public = new ModifierCollection(new Modifier("public"));
        public static ModifierCollection Internal = new ModifierCollection(new Modifier("internal"));
        public static ModifierCollection Protected = new ModifierCollection(new Modifier("protected"));

        public static ModifierCollection Abstract = new ModifierCollection(new Modifier("abstract"));
        public static ModifierCollection Constant = new ModifierCollection(new Modifier("const"));
        public static ModifierCollection Event = new ModifierCollection(new Modifier("event"));
        public static ModifierCollection New = new ModifierCollection(new Modifier("new"));
        public static ModifierCollection Override = new ModifierCollection(new Modifier("override"));
        public static ModifierCollection Partial = new ModifierCollection(new Modifier("partial"));
        public static ModifierCollection ReadOnly = new ModifierCollection(new Modifier("readonly"));
        public static ModifierCollection Sealed = new ModifierCollection(new Modifier("sealed"));
        public static ModifierCollection Static = new ModifierCollection(new Modifier("static"));
        public static ModifierCollection Virtual = new ModifierCollection(new Modifier("virtual"));
        public static ModifierCollection Async = new ModifierCollection(new Modifier("async"));

        public static ModifierCollection PrivateAbstract = new ModifierCollection(Modifiers.Private, Modifiers.Abstract);
        public static ModifierCollection PrivateConstant = new ModifierCollection(Modifiers.Private, Modifiers.Constant);
        public static ModifierCollection PrivateEvent = new ModifierCollection(Modifiers.Private, Modifiers.Event);
        public static ModifierCollection PrivateNew = new ModifierCollection(Modifiers.Private, Modifiers.New);
        public static ModifierCollection PrivateOverride = new ModifierCollection(Modifiers.Private, Modifiers.Override);
        public static ModifierCollection PrivatePartial = new ModifierCollection(Modifiers.Private, Modifiers.Partial);
        public static ModifierCollection PrivatePartialStatic = new ModifierCollection(Modifiers.Private, Modifiers.Partial, Modifiers.Static);
        public static ModifierCollection PrivateReadOnly = new ModifierCollection(Modifiers.Private, Modifiers.ReadOnly);
        public static ModifierCollection PrivateSealed = new ModifierCollection(Modifiers.Private, Modifiers.Sealed);
        public static ModifierCollection PrivateStatic = new ModifierCollection(Modifiers.Private, Modifiers.Static);
        public static ModifierCollection PrivateVirtual = new ModifierCollection(Modifiers.Private, Modifiers.Virtual);


        public static ModifierCollection PublicAbstract = new ModifierCollection(Modifiers.Public, Modifiers.Abstract);
        public static ModifierCollection PublicConstant = new ModifierCollection(Modifiers.Public, Modifiers.Constant);
        public static ModifierCollection PublicEvent = new ModifierCollection(Modifiers.Public, Modifiers.Event);
        public static ModifierCollection PublicNew = new ModifierCollection(Modifiers.Public, Modifiers.New);
        public static ModifierCollection PublicOverride = new ModifierCollection(Modifiers.Public, Modifiers.Override);
        public static ModifierCollection PublicPartial = new ModifierCollection(Modifiers.Public, Modifiers.Partial);
        public static ModifierCollection PublicPartialStatic = new ModifierCollection(Modifiers.Public, Modifiers.Partial, Modifiers.Static);
        public static ModifierCollection PublicReadOnly = new ModifierCollection(Modifiers.Public, Modifiers.ReadOnly);
        public static ModifierCollection PublicSealed = new ModifierCollection(Modifiers.Public, Modifiers.Sealed);
        public static ModifierCollection PublicStatic = new ModifierCollection(Modifiers.Public, Modifiers.Static);
        public static ModifierCollection PublicVirtual = new ModifierCollection(Modifiers.Public, Modifiers.Virtual);

        public static ModifierCollection PublicAsync = new ModifierCollection(Modifiers.Public, Modifiers.Async);

        public static ModifierCollection InternalAbstract = new ModifierCollection(Modifiers.Internal, Modifiers.Abstract);
        public static ModifierCollection InternalConstant = new ModifierCollection(Modifiers.Internal, Modifiers.Constant);
        public static ModifierCollection InternalEvent = new ModifierCollection(Modifiers.Internal, Modifiers.Event);
        public static ModifierCollection InternalNew = new ModifierCollection(Modifiers.Internal, Modifiers.New);
        public static ModifierCollection InternalOverride = new ModifierCollection(Modifiers.Internal, Modifiers.Override);
        public static ModifierCollection InternalPartial = new ModifierCollection(Modifiers.Internal, Modifiers.Partial);
        public static ModifierCollection InternalPartialStatic = new ModifierCollection(Modifiers.Internal, Modifiers.Partial, Modifiers.Static);
        public static ModifierCollection InternalReadOnly = new ModifierCollection(Modifiers.Internal, Modifiers.ReadOnly);
        public static ModifierCollection InternalSealed = new ModifierCollection(Modifiers.Internal, Modifiers.Sealed);
        public static ModifierCollection InternalStatic = new ModifierCollection(Modifiers.Internal, Modifiers.Static);
        public static ModifierCollection InternalVirtual = new ModifierCollection(Modifiers.Internal, Modifiers.Virtual);
        public static ModifierCollection InternalAsync = new ModifierCollection(Modifiers.Internal, Modifiers.Async);

        public static ModifierCollection ProtectedAbstract = new ModifierCollection(Modifiers.Protected, Modifiers.Abstract);
        public static ModifierCollection ProtectedConstant = new ModifierCollection(Modifiers.Protected, Modifiers.Constant);
        public static ModifierCollection ProtectedEvent = new ModifierCollection(Modifiers.Protected, Modifiers.Event);
        public static ModifierCollection ProtectedNew = new ModifierCollection(Modifiers.Protected, Modifiers.New);
        public static ModifierCollection ProtectedOverride = new ModifierCollection(Modifiers.Protected, Modifiers.Override);
        public static ModifierCollection ProtectedPartial = new ModifierCollection(Modifiers.Protected, Modifiers.Partial);
        public static ModifierCollection ProtectedPartialStatic = new ModifierCollection(Modifiers.Protected, Modifiers.Partial, Modifiers.Static);
        public static ModifierCollection ProtectedReadOnly = new ModifierCollection(Modifiers.Protected, Modifiers.ReadOnly);
        public static ModifierCollection ProtectedSealed = new ModifierCollection(Modifiers.Protected, Modifiers.Sealed);
        public static ModifierCollection ProtectedStatic = new ModifierCollection(Modifiers.Protected, Modifiers.Static);
        public static ModifierCollection ProtectedVirtual = new ModifierCollection(Modifiers.Protected, Modifiers.Virtual);

    }

}
